<template>
  <a-modal
    :width="450"
    :visible="visible"
    :title="title"
    :footer="null"
    @cancel="onClose"
    :maskClosable="false"
    :destroyOnClose="true"
  >
    <div class="pay-content">
      <div v-if="payType === 'pay'" class="pay-gun-box">
        <div class="pay-gun-content">
          <div class="pay-gun-main">
            <div class="pay-right space-between">
              <div class="pay-title">
                <cu-icon class="scan-icon" type="org-saoma" />
                扫描用户付款码支付
              </div>
              <div>
                <a-input
                  autofocus
                  ref="scanInput"
                  class="w-100p"
                  :disabled="!canScan"
                  :placeholder="!canScan ? '请配置支付方式' : ''"
                  v-model:value="payCode"
                >
                  <template #suffix>
                    <WechatOutlined v-if="haveWx" :style="{color: '#07c160', marginRight: haveAl ? '6px' : 0}" />
                    <AlipayOutlined v-if="haveAl" style="color: #1677ff"/>
                  </template>
                </a-input>
                <div class="pay-tips ptb-8">
                  <cu-icon type="org-xinxi" class="tips-icon" />
                  可使用扫码枪直接扫描，或者先刷新用户微信中的码再填写
                </div>
              </div>
            </div>
          </div>
        </div>
        <a-row type="flex" justify="end" align="middle">
          <a-button
            type="primary"
            :disabled="!payCode"
            :loading="payLoading"
            @click.stop="goPay"
          >确认支付</a-button>
        </a-row>
      </div>
      <div v-if="payType === 'pay'" class="pay-weixin-box">
        <div class="pay-gun-content">
          <div class="pay-gun-main">
            <div class="pay-right">
              <div class="pay-title">
                <cu-icon class="scan-icon-1" type="org-saoma1" />
                用户扫二维码付款
              </div>
              <div class="qr-code-box">
                <qrcode-vue
                  :value="qrcodeUrl"
                  :size="80"
                  id="pay-qr-code"
                  class="pay-qr"
                  @click="showBigQr"
                />
                <div class="pay-tips ml-8">
                  <cu-icon type="org-xinxi" class="tips-icon" />
                  点击二维码可以放大展示，用户若使用该方式支付成功，会自动清缴账单，关闭即可
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <a-result
        v-else
        :status="payType"
        :title="payType === 'success' ? '支付成功' : '支付失败'"
        :subTitle="errTips"
      >
        <template #extra>
          <a-button v-if="payType === 'success'" @click.stop="goBack">返回</a-button>
          <a-button v-if="payType === 'error'" @click.stop="repay">重新支付</a-button>
        </template>
      </a-result>
    </div>

    <a-modal v-model:visible="showBig" title="付款二维码"  :footer="null" @cancel="showBig = false" destroyOnClose>
      <div class="modal-qr-main">
        <qrcode-vue
          :value="qrcodeUrl"
          :size="300"
          id="pay-qr-code-big"
        />
      </div>
    </a-modal>
  </a-modal>
</template>

<script>
import {computed, defineComponent, reactive, toRefs, ref, watch, onBeforeUnmount} from "vue";
import QrcodeVue from "qrcode.vue";
import { WechatOutlined, AlipayOutlined } from "@ant-design/icons-vue";
import {} from "@ant-design/icons-vue";
import store from "@/store";
import request from "@/common/utils/request";
import {message, Result} from "ant-design-vue";
export default defineComponent({
  name: "OnlinePayment",
  components: { QrcodeVue, WechatOutlined, AlipayOutlined, "a-result": Result, },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    qrcodeUrl: {
      type: String,
      default: "",
    },
    orderId: {
      type: String,
      default: '',
    }
  },
  setup(props, { emit }) {
    const state = reactive({
      payType: "pay", // pay 在线支付 success 支付成功 error 支付失败
      payCode: '',
      payLoading: false,
      canScan: false,
      haveWx: false,
      haveAl: false,
      payMethod: {},
      trade_no: '', // 流水号
      errTips: '',
      showBig: false,
      loopPay: null, // 一开始就进来
      loopResult: null, // 扫码枪轮询
    });
    const scanInput = ref(null);

    const title = computed(() => {
      return state.payType === 'pay' ? "在线支付" : "支付结果";
    });

    const clearLoop = () => {
      if (state.loopPay) {
        clearTimeout(state.loopPay);
      }
      if (state.loopResult) {
        clearTimeout(state.loopResult);
      }
    }

    // 获取支付结果
    const getPayResult = () => {
      request.post("/pay", "/pay/order/sync_after", {trade_no: state.trade_no, auth_code: state.payCode}).then((res) => {
        const {
          status,
          msg,
        } = res
        if (status === "wait") {
          state.loopResult = setTimeout(() => {
            getPayResult();
          }, 2000)
        } else if (['paid', 'goUrl'].includes(status)) {
          // 成功
          clearLoop();
          state.payLoading = false;
          state.payType = 'success';
          state.payCode = '';
          emit("paySuccess");
        } else if (status === 'error') {
          state.payLoading = false;
          state.payType = 'error';
          state.payCode = '';
          state.errTips = msg || '';
        }
      })
    }

    const goPay = () => {
      state.payLoading = true;
      let params = {
        order_id: props.orderId,
        cur_env: 'authCode',
        pay_id_arr: state.payMethod,
        auth_code: state.payCode,
      }
      request.post("/pay", "/pay/order/param", params).then((res) => {
        if (res.status === 'wait') {
          state.trade_no = res.trade_no;
          // 开启轮询
          getPayResult();
        } else if (res.status === 'goUrl' || res.status === 'ok') {
          state.payLoading = false;
          state.payType = 'success';
          state.payCode = '';
          emit("paySuccess");
        } else if (res.status === 'error') {
          state.payLoading = false;
          state.payType = 'error';
          state.payCode = '';
        }
      }).catch((err) => {
        message.warning(err?.msg || '支付异常');
        state.payLoading = false;
      })
    }

    const onClose = () => {
      clearLoop();
      emit("payClose");
    };

    const getPayResultLoop = () => {
      let params = {
        order_id: props.orderId
      }
      request.post("/pay", "/pay/order/sync_after", params).then((res) => {
        const {
          status,
        } = res
        if (status === "wait") {
          state.loopPay = setTimeout(() => {
            getPayResultLoop();
          }, 3000);
        } else if (['paid', 'goUrl'].includes(status)) {
          // 成功
          clearLoop();
          state.payLoading = false;
          state.payType = 'success';
          emit("paySuccess");
          state.payCode = '';
        }
      })
    };

    const getPayMethods = () => {
      getPayResultLoop();
      request.get("/pay", "/pay/order/get", {order_id: props.orderId, cur_env: 'authCode'}).then((res) => {
        // 支持支付宝或者 微信 才能扫 扫码枪 且 聚焦
        let methodList = res?.methodList || [];
        methodList.forEach((v) => {
          if (v.pay_method === 'wxpay' ) {
            state.canScan = true;
            state.haveWx = true;
          }
          if (v.pay_method === 'alipay') {
            state.canScan = true;
            state.haveAl = true;
          }
          state.payMethod[v.pay_method] = v.pay_id;
        })
        if (state.canScan) {
          setTimeout(() => {
            scanInput?.value?.focus();
          }, 0)
        }
      })
    };

    const goBack = () => {
      clearLoop();
      emit("goBack");
    };

    // 重新支付
    const repay = () => {
      state.payType = "pay";
      state.payCode = '';
      state.payLoading = false;
      state.trade_no = '';
      state.errTips = '';
      setTimeout(() => {
        scanInput?.value?.focus();
      }, 0);
    }

    const reset = () => {
      clearLoop();
      state.payType = "pay";
      state.payCode = '';
      state.payLoading = false;
      state.canScan = false;
      state.haveWx = false;
      state.haveAl = false;
      state.payMethod = {};
      state.trade_no = '';
      state.errTips = '';
      state.loopPay = null;
      state.loopResult = null;
      state.showBig = false;
    };

    watch(
      () => props.visible,
      (val) => {
        if (val) {
          getPayMethods();
        } else {
          reset();
        }
      }
    );

    const showBigQr = () => {
      state.showBig = true;
    }

    onBeforeUnmount(() => {
      clearLoop();
    });

    return {
      ...toRefs(state),
      title,
      scanInput,
      goPay,
      onClose,
      goBack,
      repay,
      showBigQr,
    };
  },
});
</script>

<style lang="less" scoped>
.pay-content {
  height: 310px;
  width: 100%;
  display: flex;
  padding: 0 10px;
  flex-direction: column;
}
.pay-gun-box {
  flex: 1;
  display: flex;
  flex-direction: column;
  margin-bottom: 24px;
}
.pay-gun-content {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}
.pay-weixin-box {
  flex: 1;
  display: flex;
}
.pay-gun-main {
  height: 100%;
  width: 100%;
  display: flex;
}
.h-100 {
  height: 100%;
}
.scan-icon {
  font-size: 18px;
  color: @primary-color;
}
.scan-icon-1 {
  font-size: 18px;
  color: @primary-color;
}
.pay-left {
  width: 30%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.space-between {
  justify-content: space-between;
}
.pay-right {
  flex: 1;
  display: flex;
  flex-direction: column;

}
.pay-title {
  font-size: 18px;
  font-weight: 600;
  color: #444;
}
.pay-tips {
  font-size: 12px;
  color: #999;
}
.tips-icon {
  font-size: 14px;
  color: @primary-color;
}
.ptb-8 {
  padding: 8px 0;
}
.ml-8 {
  margin-left: 8px;
}
.qr-code-box {
  display: flex;
  margin-top: 20px;
}
.dec-box {
  width: 100%;
}
:deep(.ant-result) {
  padding: 20px 80px;
}
:deep(.ant-result-subtitle) {
  margin-top: 12px;
  color: #475259;
}
.pay-qr {
  cursor: pointer;
}
.modal-qr-main {
  display: flex;
  justify-content: center;
}
</style>
